using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;

namespace XnaDevRu.Bullet
{
	public class StaticPlaneShape : ConcaveShape
	{
		private Vector3 _localAabbMin;
		private Vector3 _localAabbMax;

		private Vector3 _planeNormal;
		private float _planeConstant;
		private Vector3 _localScaling;

		public StaticPlaneShape(Vector3 planeNormal, float planeConstant)
		{
			_planeNormal = planeNormal;
			_planeConstant = planeConstant;
			_localScaling = new Vector3();
		}

		protected Vector3 LocalAabbMin { get { return _localAabbMin; } set { _localAabbMin = value; } }
		protected Vector3 LocalAabbMax { get { return _localAabbMax; } set { _localAabbMax = value; } }

		protected Vector3 PlaneNormal { get { return _planeNormal; } set { _planeNormal = value; } }
		protected float PlaneConstant { get { return _planeConstant; } set { _planeConstant = value; } }

		public override BroadphaseNativeTypes ShapeType
		{
			get
			{
				return BroadphaseNativeTypes.StaticPlane;
			}
		}

		public override Vector3 LocalScaling
		{
			get
			{
				return _localScaling;
			}
			set
			{
				_localScaling = value;
			}
		}

		public override string Name
		{
			get
			{
				return "StaticPlane";
			}
		}

		public override void GetAabb(Matrix t, out Vector3 aabbMin, out Vector3 aabbMax)
		{
			Vector3 infvec = new Vector3(1e30f, 1e30f, 1e30f);

			Vector3 center = _planeNormal * _planeConstant;
			aabbMin = center + infvec * _planeNormal;
			aabbMax = aabbMin;
			MathHelper.SetMin(ref aabbMin, center - infvec * _planeNormal);
			MathHelper.SetMax(ref aabbMax, center - infvec * _planeNormal);

			aabbMin = new Vector3(-1e30f, -1e30f, -1e30f);
			aabbMax = new Vector3(1e30f, 1e30f, 1e30f);
		}

		public override void CalculateLocalInertia(float mass, out Vector3 inertia)
		{
			//moving concave objects not supported
			inertia = new Vector3();
		}

        public override void ProcessAllTriangles(ITriangleCallback callback, Vector3 aabbMin, Vector3 aabbMax) {
            Vector3 halfExtents = (aabbMax - aabbMin) * 0.5f;
            float radius = halfExtents.Length();
            Vector3 center = (aabbMax + aabbMin) * 0.5f;

            //this is where the triangles are generated, given AABB and plane equation (normal/constant)
            Vector3 tangentDir0 = new Vector3(), tangentDir1 = new Vector3();

            //tangentDir0/tangentDir1 can be precalculated
            MathHelper.PlaneSpace1(_planeNormal, ref tangentDir0, ref tangentDir1);

            Vector3 projectedCenter = center - (Vector3.Dot(_planeNormal, center) - _planeConstant) * _planeNormal;

            Vector3[] triangle = new Vector3[3];
            triangle[0] = projectedCenter + tangentDir0 * radius + tangentDir1 * radius;
            triangle[1] = projectedCenter + tangentDir0 * radius - tangentDir1 * radius;
            triangle[2] = projectedCenter - tangentDir0 * radius - tangentDir1 * radius;
            callback.ProcessTriangle(triangle, 0, 0);

            triangle[0] = projectedCenter - tangentDir0 * radius - tangentDir1 * radius;
            triangle[1] = projectedCenter - tangentDir0 * radius + tangentDir1 * radius;
            triangle[2] = projectedCenter + tangentDir0 * radius + tangentDir1 * radius;
            callback.ProcessTriangle(triangle, 0, 1);
        }
    }
}
